Introduction
Welcome!
Code Examples
Day 1
Challenge: KISS
Solution: KISS
Day 2
Challenge: Type Annotations
Solution: Type Annotations
Day 3
Challenge: Decoupling
Solution: Decoupling
Day 4
Challenge: DRY
Solution: DRY
Day 5
Challenge: String Formatting
Solution: String Formatting
Day 6
Challenge: Law Of Demeter
Solution: Law Of Demeter
Day 7
Challenge: Better Discounts
Solution: Better Discounts
Day 8
Challenge: Payment Strategy
Solution: Payment Strategy
Day 9
Challenge: Plugins
Solution: Plugins
Day 10
Challenge: Object Oriented To Functional
Solution: Object Oriented To Functional
Day 11
Challenge: Cohesion
Solution: Cohesion
Day 12
Challenge: MVP
Solution: MVP
Day 13
Challenge: Inheritance
Solution: Inheritance
Day 14
Challenge: Abstraction
Solution: Abstraction
Day 15
Challenge: Higher-Order Functions
Solution: Higher-Order Functions
Day 16
Challenge: Configuration
Solution: Configuration
Day 17
Challenge: Concurrency
Solution: Concurrency
Day 18
Challenge: Refactoring
Solution: Refactoring
Day 19
Challenge: Itertools
Solution: Itertools
Day 20
Challenge: Inappropriate Intimacy
Solution: Inappropriate Intimacy
Wrap Up
End of Part 1

why not doing something like this ?
@dataclass
class Geolocation:
id: int
street: str
postal_code: str
city: str
province: str
latitude: float
longitude: float
def __post_init__(self):
self.breadcrumbs: dict[str, str] = {}
main_url = "https://myapi.com"
self.breadcrumbs[
"postal_code_url"
] = f"{main_url}/postal_code/{self.postal_code}/"
city_slug = self.city.lower().replace(" ", "-")
self.breadcrumbs["city_url"] = f"{main_url}/region/{city_slug}/"
self.breadcrumbs[
"province_url"
] = f"{main_url}/region/province/{self.province.lower()}/"
Hi Roberto, the issue with this approach is that now there is no way to generate breadcrumbs with anything that's not a Geolocation, and you also can't do it separately anymore from creating the Geolocation object. If you create a Geolocation object, and then change the postal code, the breadcrumbs won't be updated. I much prefer keeping it as a separate function.
My solution trying several things:
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class Geolocation:
id: int
street: str
postal_code: str
city: str
province: str
latitude: float
longitude: float
@dataclass
class Location:
id: int
message_id: str
raw_data: str
date: datetime
priority: int
geolocation: list[Geolocation] = field(default_factory=list)
@dataclass
class BreadCrumb:
postal_code: str
city: str
province: str
def generate_breadcrumbs(geolocation: Geolocation) -> dict[str, str]:
breadcrumbs: dict[str, str] = {}
main_url = "https://myapi.com"
if geolocation:
if geolocation.postal_code:
breadcrumbs[
"postal_code_url"
] = f"{main_url}/postal_code/{geolocation.postal_code}/"
if geolocation.city:
city_slug = geolocation.city.lower().replace(" ", "-")
breadcrumbs["city_url"] = f"{main_url}/region/{city_slug}/"
if geolocation.province:
breadcrumbs[
"province_url"
] = f"{main_url}/region/province/{geolocation.province.lower()}/"
return breadcrumbs
def generate_breadcrumbs_with(
postal_code: str, city: str, province: str
) -> dict[str, str]:
breadcrumbs: dict[str, str] = {}
main_url = "https://myapi.com"
if postal_code:
breadcrumbs["postal_code_url"] = f"{main_url}/postal_code/{postal_code}/"
if city:
city_slug = city.lower().replace(" ", "-")
breadcrumbs["city_url"] = f"{main_url}/region/{city_slug}/"
if province:
breadcrumbs["province_url"] = f"{main_url}/region/province/{province.lower()}/"
return breadcrumbs
def generate_with_breadcrumbs(breadcrumb: BreadCrumb) -> dict[str, str]:
breadcrumbs: dict[str, str] = {}
main_url = "https://myapi.com"
if breadcrumb.postal_code:
breadcrumbs[
"postal_code_url"
] = f"{main_url}/postal_code/{breadcrumb.postal_code}/"
if breadcrumb.city:
city_slug = breadcrumb.city.lower().replace(" ", "-")
breadcrumbs["city_url"] = f"{main_url}/region/{city_slug}/"
if breadcrumb.province:
breadcrumbs[
"province_url"
] = f"{main_url}/region/province/{breadcrumb.province.lower()}/"
return breadcrumbs
def main() -> None:
location = Location(
id=1,
message_id="123456",
raw_data="raw data",
date=datetime.now(),
priority=1,
geolocation=[
Geolocation(
id=1,
street="123 Main St",
postal_code="12345",
city="New York",
province="NY",
latitude=40.7128,
longitude=74.0060,
)
],
)
breadcrumbs = generate_breadcrumbs(location.geolocation[0])
postal_code = location.geolocation[0].postal_code
city = location.geolocation[0].city
province = location.geolocation[0].province
breadcrumb = BreadCrumb(postal_code, city, province)
other_breadcrumbs = generate_breadcrumbs_with(postal_code, city, province)
yet_another_bc = generate_with_breadcrumbs(breadcrumb)
print(breadcrumbs)
print(other_breadcrumbs)
print(yet_another_bc)
if __name__ == "__main__":
main()
You could also move the breadcrumbs method to be a property of the Geolocation class, that way you don't need to know about the internals, via print(geolocation.breadcrumbs).
Good suggestion!
The interesting thing is that there always seems to be a trade off - on the one hand we reduce the implementation details that are exposed externally but on the other hand maybe we add too much responsibility to the Geolocation class which is more about locations and not breadcrumbs. That’s the hard part to know!